//
//  CJFile.swift
//  CJPack
//
//  Created by 陈警卫 on 2024-05-24.
//

import UIKit
import Foundation

// MARK: - 文件操作

open class CJFile: NSObject {
    
    /// 判断文件存在
    @objc static public func fileExist(_ path: String) -> Bool {
        let exist = FileManager.default.fileExists(atPath: path)
        return exist
    }
    
    /// 创建文件夹
    @discardableResult
    @objc static public func createFolder(_ path: String) -> Bool {
        if fileExist(path) {
            return true
        }
        do {
            try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true)
            return true
        } catch {
            print("[CJFile]创建文件夹失败\(error)")
            return false
        }
    }
    
    /// 删除文件夹
    @discardableResult
    @objc static public func removeFolder(_ path: String) -> Bool {
        if fileExist(path) {
            do {
                try FileManager.default.removeItem(atPath: path)
                return true
            } catch {
                print("[CJFile]删除文件夹失败\(error)")
                return false
            }
        } else {
            return true
        }
    }
    
    /// 创建文件
    @discardableResult
    @objc static public func createFile(_ path: String) -> Bool {
        // 判断文件夹路径 没有就创建
        let foldPath = (path as NSString).deletingLastPathComponent
        if !fileExist(foldPath) {
            if !createFolder(foldPath) {
                print("[CJFile]创建文件失败")
                return false
            }
        }
        if fileExist(path) {
            return true
        }
        let result = FileManager.default.createFile(atPath: path, contents: nil)
        if !result {
            print("[CJFile]创建文件失败")
        }
        return result
    }
    
    /// 删除文件
    @discardableResult
    @objc static public func removeFile(_ path: String) -> Bool {
        if fileExist(path) {
            do {
                try FileManager.default.removeItem(atPath: path)
                return true
            } catch {
                print("[CJFile]删除文件失败\(error)")
                return false
            }
        } else {
            return true
        }
    }
    
    /// 读取文件
    @objc static public func readFile(_ path: String) -> Data? {
        if fileExist(path) {
            let data = FileManager.default.contents(atPath: path)
            return data
        } else {
            return nil
        }
    }
}

extension CJFile {
    
    /// 写入文件
    @discardableResult
    static func writeFile(_ path: String, value: String, atomically: Bool = true) -> Bool {
        if !createFile(path) { return false }
        do {
            try value.write(toFile: path, atomically: atomically, encoding: .utf8)
            return true
        } catch {
            print("[CJFile]写入文件失败\(error)")
            return false
        }
    }

    /// 写入文件
    @discardableResult
    static func writeFile(_ path: String, value: NSArray, atomically: Bool = true) -> Bool {
        if !createFile(path) { return false }
        if value.write(toFile: path, atomically: atomically) {
            return true
        } else {
            print("[CJFile]写入文件失败")
            return false
        }
    }

    /// 写入文件
    @discardableResult
    static func writeFile(_ path: String, value: NSDictionary, atomically: Bool = true) -> Bool {
        if !createFile(path) { return false }
        if value.write(toFile: path, atomically: atomically) {
            return true
        } else {
            print("[CJFile]写入文件失败")
            return false
        }
    }

    /// 写入文件
    @discardableResult
    static func writeFile(_ path: String, value: UIImage, atomically: Bool = true) -> Bool {
        guard let data = value.pngData() else { return false }
        return writeFile(path, value: data, atomically: atomically)
    }

    /// 写入文件
    @discardableResult
    static func writeFile(_ path: String, value: Data, atomically: Bool = true) -> Bool {
        if !createFile(path) { return false }
        do {
            try value.write(to: URL(fileURLWithPath: path), options: (atomically ? .atomic : []))
            return true
        } catch {
            print("[CJFile]写入文件失败\(error)")
            return false
        }
    }
}


// MARK: - 文件路径

public extension CJFile {
    
    /// Home path Url
    @objc static var homePathUrl: URL {
        let homePathUrl = URL(fileURLWithPath: NSHomeDirectory())
        return homePathUrl
    }
    
    /// Document path Url
    @objc static var documentPathUrl: URL? {
        let documentPathUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
        return documentPathUrl
    }
    
    /// Library path Url
    @objc static var libraryPathUrl : URL? {
        let libraryPathUrl = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first
        return libraryPathUrl
    }
    
    /// Caches path Url
    @objc static var cachesPathUrl: URL? {
        let cachesPathUrl = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first
        return cachesPathUrl
    }
    
    /// Preferences path Url
    @objc static var preferencesPathUrl: URL? {
        let preferencesPathUrl = libraryPathUrl?.appendingPathComponent("Preferences")
        return preferencesPathUrl
    }
    
    /// tmp path Url
    @objc static var tmpPathUrl: URL {
        let tmpPathUrl = homePathUrl.appendingPathComponent("tmp")
        return tmpPathUrl
    }
    
    @objc static var homePath: String { homePathUrl.path }
    @objc static var documentsPath: String { documentPathUrl?.path ?? "" }
    @objc static var libraryPath: String { libraryPathUrl?.path ?? "" }
    @objc static var cachesPath: String { cachesPathUrl?.path ?? "" }
    @objc static var preferencesPath: String { preferencesPathUrl?.path ?? "" }
    @objc static var tmpPath: String { tmpPathUrl.path }
}

// MARK: - 文件处理

open class CJFileHandle: NSObject {
    
    /// 数据写入文件
    @discardableResult
    @objc static public func write(_ path: String, value: String) -> Bool {
        if let data = value.data(using: .utf8) {
            return write(path, data: data)
        }
        return false
    }
    
    /// 数据写入文件
    @discardableResult
    @objc static public func write(_ path: String, data: Data) -> Bool {
        // 判断文件路径
        let exist = CJFile.fileExist(path)
        if !exist {
            CJFile.createFile(path)
        }
        do {
            let fileHandle = try FileHandle(forWritingTo: URL(fileURLWithPath: path))
            fileHandle.seekToEndOfFile()
            fileHandle.write(data)
            try fileHandle.synchronize()
            fileHandle.closeFile()
            return true
        } catch {
            print("[CJFileHandle]数据写入文件失败\(error)")
            return false
        }
    }
}
